﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.ExtendedReflection.Metadata;
using System.Reflection;
using Microsoft.ExtendedReflection.Utilities.Safe.Diagnostics;
using DUCover.Core;

namespace DUCover.Static
{
    /// <summary>
    /// Uses static analysis to collect all declared entities in the program
    /// </summary>
    public class DeclEntityCollector
    {
        static AllDeclEntity ade = null;


        /// <summary>
        /// Analyzes the given assembly statically and gathers all declared entities
        /// such as member variables and local variables
        /// </summary>
        /// <param name="assembly"></param>
        public static void CollectAllDeclEntitiesInAssembly(AssemblyEx assembly)
        {
            SafeDebug.AssumeNotNull(assembly, "assembly");

            if (ade == null)
            {
                ade = AllDeclEntity.GetInstance();
            }

            foreach (TypeDefinition td in assembly.TypeDefinitions)
            {
                CollectAllDeclEntitiesInTypeDef(td);

                foreach (MethodDefinition md in td.DeclaredStaticMethods)
                {
                    CollectAllDeclEntitiesInMethodDef(md);
                }

                foreach (MethodDefinition md in td.DeclaredInstanceMethods)
                {
                    CollectAllDeclEntitiesInMethodDef(md);
                }
            }
        }

        /// <summary>
        /// Collects all declared entities within a method
        /// </summary>
        /// <param name="md"></param>
        private static void CollectAllDeclEntitiesInMethodDef(MethodDefinition md)
        {
            //TODO: How to extend the current analysis for local variables of members

            //foreach (ParameterDefinition pd in md.Parameters)
            //{
            //    DeclEntity de = new DeclEntity(pd);
            //    ade.AddDeclEntity(de);
            //}            
        }

        /// <summary>
        /// Collects all declared entities in a class
        /// </summary>
        /// <param name="td"></param>
        private static void CollectAllDeclEntitiesInTypeDef(TypeDefinition td)
        {
            foreach (FieldDefinition fd in td.DeclaredInstanceFields)
            {
                DeclEntity de = new DeclEntity(fd);
                ade.AddDeclEntity(de);
            }

            foreach (FieldDefinition fd in td.DeclaredStaticFields)
            {
                DeclEntity de = new DeclEntity(fd);
                ade.AddDeclEntity(de);
            }
        }
    }
}
